package com.blue.fish.tiny.common;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.stream.Stream;

/**
 * @author QingFan
 * @version 1.0.0
 * @date 2023年01月05日 21:45
 */
public class PeekIterator<T> implements Iterator<T> {

	private final Iterator<T> it;

	private final LinkedList<T> queueCache = new LinkedList<>();
	private final LinkedList<T> stackPutBack = new LinkedList<>();
	private static final int CACHE_SIZE = 10;

	private T _endToken;

	public PeekIterator(Stream<T> source) {
		it = source.iterator();
	}

	public PeekIterator(Stream<T> source, T endToken) {
		it = source.iterator();
		this._endToken = endToken;
	}

	public T peek() {
		if (stackPutBack.size() > 0) {
			return stackPutBack.getFirst();
		}
		if (!it.hasNext()) {
			return _endToken;
		}
		T val = next();
		putBack();
		return val;
	}

	public void putBack() {
		// 缓存:A -> B -> C -> D
		// 放回:D -> C -> B -> A
		if (queueCache.size() > 0) {
			stackPutBack.push(queueCache.pollLast());
		}
	}

	@Override
	public boolean hasNext() {
		return _endToken != null || stackPutBack.size() > 0 || it.hasNext();
	}

	@Override
	public T next() {
		T val = null;
		if (stackPutBack.size() > 0) {
			val = stackPutBack.pop();
		} else {
			if (!it.hasNext()) {
				T t = _endToken;
				_endToken = null;
				return t;
			}
			val = it.next();
		}
		while (queueCache.size() > CACHE_SIZE - 1) {
			queueCache.poll();
		}
		queueCache.add(val);
		return val;
	}
}
